package com.david.dubbo.router;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.cache.PathChildrenCache;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheEvent;
import org.apache.curator.framework.recipes.cache.PathChildrenCacheListener;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author David
 * @version V1.0
 * @Package com.david.dubbo.router
 * @date 2021/4/15 23:31
 */
public class ReadyRestartInstances implements PathChildrenCacheListener {

    private static final Logger logger= LoggerFactory.getLogger(ReadyRestartInstances.class);
    //监听的路径
    private static final String LISTHEN_PATH="/david/dubbo/restart/instances";
    //存放正在重启的节点信息
    private volatile Set<String> restartInstances=new HashSet<>();

    private final CuratorFramework client;

    private ReadyRestartInstances(CuratorFramework client) {
        this.client = client;
    }

    public static ReadyRestartInstances create(){
        //传入zkClient
        final CuratorFramework client=ZookeeperClients.client();
        //判断节点是否存在
        try {
            Stat stat = client.checkExists().forPath(LISTHEN_PATH);
            if (stat==null){
                client.create().creatingParentsIfNeeded().forPath(LISTHEN_PATH);
            }
        } catch (Exception e) {
            logger.error("节点不存在，创建节点失败！");
        }
        ReadyRestartInstances instances = new ReadyRestartInstances(client);

        //启动监听
        PathChildrenCache childrenCache = new PathChildrenCache(client, LISTHEN_PATH, false);
        childrenCache.getListenable().addListener(instances);
        try {
            childrenCache.start();
        } catch (Exception e) {
            logger.error("节点监听失败！");
        }
        return instances;
    }

    /**
     * 添加重启的服务器实例
     * @param applicationName
     * @param host
     * @throws Exception
     */
    public void addRestartingInstance(String applicationName,String host) throws Exception {
        client.create().creatingParentsIfNeeded().forPath(LISTHEN_PATH+"/"+buildApplicationAndInstanceString(applicationName,host));
    }

    /**
     * 删除重启服务器
     * @param applicationName
     * @param host
     * @throws Exception
     */
    public void deleteRestartingInstance(String applicationName,String host) throws Exception {
        client.delete().forPath(LISTHEN_PATH+"/"+buildApplicationAndInstanceString(applicationName,host));
    }

    /**
     * 判断当前服务是否在重启
     * @param applicationName
     * @param ip
     * @return
     */
    public boolean hasRestartingInstance(String applicationName,String ip){
        return restartInstances.contains(buildApplicationAndInstanceString(applicationName,ip));
    }
    private String buildApplicationAndInstanceString(String applicationName,String host){
        return applicationName+"_"+host;
    }

    @Override
    public void childEvent(CuratorFramework curatorFramework, PathChildrenCacheEvent pathChildrenCacheEvent) throws Exception {
        List<String> s = client.getChildren().forPath(LISTHEN_PATH);
        if (CollectionUtils.isEmpty(s)){
            restartInstances= Collections.EMPTY_SET;
        }else{
            restartInstances=new HashSet<>(s);
        }
    }


}
